package com.example.demo.threadCommunication;

/**
 * @desc: <br/>
 * @author: Jingbo Hu<br/>
 * @time：2020年07⽉21⽇<br/>
 * @version：v1.0.0<br>
 */
public class ThreadPoolDemo {

    /**
     * 一、线程池的处理流程
     * 1）线程池判断核心线程池里的线程是否都在执行任务。如果不是，则创建一个新的工作
     * 线程来执行任务。如果核心线程池里的线程都在执行任务，则进入下个流程。
     * 2）线程池判断工作队列是否已经满。如果工作队列没有满，则将新提交的任务存储在这
     * 个工作队列里。如果工作队列满了，则进入下个流程。
     * 3）线程池判断线程池的线程是否都处于工作状态。如果没有，则创建一个新的工作线程
     * 来执行任务。如果已经满了，则交给饱和策略来处理这个任务.
     *
     * 二、RejectedExecutionHandler（饱和策略）
     * .AbortPolicy：直接抛出异常。
     * ·CallerRunsPolicy：只用调用者所在线程来运行任务。
     * ·DiscardOldestPolicy：丢弃队列里最近的一个任务，并执行当前任务。
     * ·DiscardPolicy：不处理，丢弃掉。
     *
     * 三、提交任务
     * 可以使用两个方法向线程池提交任务，分别为execute()和submit()方法
     * execute()方法用于提交不需要返回值的任务，所以无法判断任务是否被线程池执行成功.
     * submit()方法用于提交需要返回值的任务。线程池会返回一个future类型的对象，通过这个future对象可以判断任务是否执行成功，并且可以通过future的get()方法来获取返回值，get()方
     *  法会阻塞当前线程直到任务完成，而使用get（long timeout，TimeUnit unit）方法则会阻塞当前线程一段时间后立即返回，这时候有可能任务没有执行完
     *
     * 四、关闭线程池
     * 可以通过调用线程池的shutdown或shutdownNow方法来关闭线程池。它们的原理是遍历线
     * 程池中的工作线程，然后逐个调用线程的interrupt方法来中断线程，所以无法响应中断的任务
     * 可能永远无法终止。但是它们存在一定的区别，shutdownNow首先将线程池的状态设置成
     * STOP，然后尝试停止所有的正在执行或暂停任务的线程，并返回等待执行任务的列表，而
     * shutdown只是将线程池的状态设置成SHUTDOWN状态，然后中断所有没有正在执行任务的线程。
     * 只要调用了这两个关闭方法中的任意一个，isShutdown方法就会返回true。当所有的任务
     * 都已关闭后，才表示线程池关闭成功，这时调用isTerminaed方法会返回true。至于应该调用哪
     * 一种方法来关闭线程池，应该由提交到线程池的任务特性决定，通常调用shutdown方法来关闭
     * 线程池，如果任务不一定要执行完，则可以调用shutdownNow方法
     *
     * 五、合理地配置线程池
     *  要想合理地配置线程池，就必须首先分析任务特性，可以从以下几个角度来分析。
     * ·任务的性质：CPU密集型任务、IO密集型任务和混合型任务。
     * ·任务的优先级：高、中和低。
     * ·任务的执行时间：长、中和短。
     * ·任务的依赖性：是否依赖其他系统资源，如数据库连接。
     * 性质不同的任务可以用不同规模的线程池分开处理。CPU密集型任务应配置尽可能小的
     * 线程，如配置N cpu +1个线程的线程池。由于IO密集型任务线程并不是一直在执行任务，则应配
     * 置尽可能多的线程，如2*N cpu 。混合型的任务，如果可以拆分，将其拆分成一个CPU密集型任务
     * 和一个IO密集型任务，只要这两个任务执行的时间相差不是太大，那么分解后执行的吞吐量
     * 将高于串行执行的吞吐量。如果这两个任务执行时间相差太大，则没必要进行分解。可以通过
     * Runtime.getRuntime().availableProcessors()方法获得当前设备的CPU个数。
     *
     */
}
